package com.draven.mall.dispatch;

import com.draven.mall.entity.Order;
import com.draven.mall.entity.Rider;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

/**
 * 最近骑手优先算法实现
 * 选择距离订单最近的骑手进行分配
 */
@Component
public class NearestRiderDispatchAlgorithm implements DispatchAlgorithm {

    private static final Logger log = LoggerFactory.getLogger(NearestRiderDispatchAlgorithm.class);

    @Override
    public Rider assignRider(Order order, List<Rider> availableRiders) {
        if (availableRiders == null || availableRiders.isEmpty() || order == null) {
            return null;
        }
        
        try {
            // 获取订单地址坐标（假设在实际应用中已通过地图API获取）
            double orderLatitude = getLatitudeFromAddress(order.getAddress());
            double orderLongitude = getLongitudeFromAddress(order.getAddress());
            
            // 找到距离最近的骑手
            Optional<Rider> nearestRider = availableRiders.stream()
                .min(Comparator.comparingDouble(rider -> {
                    // 获取骑手坐标，如果为null则使用默认值0
                    double riderLat = rider.getLatitude() != null ? rider.getLatitude().doubleValue() : 0;
                    double riderLng = rider.getLongitude() != null ? rider.getLongitude().doubleValue() : 0;
                    return calculateDistance(orderLatitude, orderLongitude, riderLat, riderLng);
                }));
            
            return nearestRider.orElse(null);
        } catch (Exception e) {
            log.error("计算最近骑手时发生异常", e);
            // 发生异常时，选择第一个可用骑手
            return availableRiders.isEmpty() ? null : availableRiders.get(0);
        }
    }
    
    /**
     * 计算两点之间的距离（使用简化版哈弗辛公式计算球面距离）
     */
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        // 将经纬度转换为弧度
        double radLat1 = Math.toRadians(lat1);
        double radLon1 = Math.toRadians(lon1);
        double radLat2 = Math.toRadians(lat2);
        double radLon2 = Math.toRadians(lon2);
        
        // 地球半径（千米）
        double earthRadius = 6371.0;
        
        // 使用哈弗辛公式
        double dlon = radLon2 - radLon1;
        double dlat = radLat2 - radLat1;
        double a = Math.pow(Math.sin(dlat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(dlon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = earthRadius * c;
        
        return distance;
    }
    
    /**
     * 从地址中获取纬度（在实际应用中应通过地图API获取）
     */
    private double getLatitudeFromAddress(String address) {
        // 简单地址解析示例（实际应当接入高德/百度等地图API）
        if (address == null || address.isEmpty()) {
            return 39.908823; // 默认北京坐标
        }
        
        if (address.contains("北京")) {
            return 39.908823;
        } else if (address.contains("上海")) {
            return 31.230416;
        } else if (address.contains("广州")) {
            return 23.129163;
        } else if (address.contains("深圳")) {
            return 22.543096;
        } else if (address.contains("杭州")) {
            return 30.274085;
        } else {
            return 39.908823; // 默认北京坐标
        }
    }
    
    /**
     * 从地址中获取经度（在实际应用中应通过地图API获取）
     */
    private double getLongitudeFromAddress(String address) {
        // 简单地址解析示例（实际应当接入高德/百度等地图API）
        if (address == null || address.isEmpty()) {
            return 116.397470; // 默认北京坐标
        }
        
        if (address.contains("北京")) {
            return 116.397470;
        } else if (address.contains("上海")) {
            return 121.473701;
        } else if (address.contains("广州")) {
            return 113.264435;
        } else if (address.contains("深圳")) {
            return 114.057865;
        } else if (address.contains("杭州")) {
            return 120.155070;
        } else {
            return 116.397470; // 默认北京坐标
        }
    }

    @Override
    public int getType() {
        return 2; // 算法类型：2-最近骑手优先
    }

    @Override
    public String getName() {
        return "最近骑手优先";
    }
} 